/*
    jQuery plugin for multi-direction slideDown / slideUp animation.
    Copyright (c) 2010 Keiji Hokamura (famteam)
    This plugin available for use in all personal or commercial projects under both MIT and GPL licenses.
 */

(function($) {
	var methods = {
		_getContainer: function(settings, self) {
			var container = self.parent();
			if (container.attr('class') != $.maskFade.CONTAINER_CLASS) {
				container = $('<div class="' + $.maskFade.CONTAINER_CLASS + '" />');
				if (self.css('position') == 'absolute') {
					container.css('position', 'absolute').css('left', settings.left != null ? settings.left : self.css('left')).css('top', settings.top != null ? settings.top : self.css('top'));
					self.css('left', 0).css('top', 0);
				}
				else {
					moveCSSAttributes = ['margin-right', 'margin-left', 'margin-top', 'margin-bottom', 'float'];
					for (var i = 0; i < moveCSSAttributes.length; i++) {
						container.css(moveCSSAttributes[i], self.css(moveCSSAttributes[i]));
						self.css(moveCSSAttributes[i], 0);
					}
				}
				self.before(container).appendTo(container);
			}
			container.css('overflow', 'hidden').width(self.width()).height(self.height());
			return container;
		},
		setup: function(settings, self) {
			methods._getContainer(settings, self);
			return self;
		},
		setupOut: function(settings, self) {
			var data = {
				settings: settings,
				left: parseInt(self.css('left')),
				top: parseInt(self.css('top')),
				marginLeft: parseInt(self.css('margin-left')),
				marginRight: parseInt(self.css('margin-top'))
			};
			var container = methods._getContainer(settings, self);
			return self.data($.maskFade.DATA, data);
		},
		startOut: function(self) {
			var container = self.parent();
			var data = self.data($.maskFade.DATA);
			var settings = data.settings;
			if (data != null) {
				switch (settings.direction) {
					case $.maskFade.TOP_TO_BOTTOM:
						container.height(self.height() - settings.verticalOffset).delay(settings.delay).animate({
							height: 0
						}, settings.duration, settings.easeType, function() {
							self.data($.maskFade.DATA, null);
							if (settings.completeHandler != null) {
								settings.completeHandler();
							}
						});
						break;
					case $.maskFade.LEFT_TO_RIGHT:
						container.width(self.width() - settings.horizontalOffset).delay(settings.delay).animate({
							width: 0
						}, settings.duration, settings.easeType, function() {
							self.data($.maskFade.DATA, null);
							if (settings.completeHandler != null) {
								settings.completeHandler();
							}
						});
						break;
					case $.maskFade.RIGHT_TO_LEFT:
						break;
				}
			}
			return self;
		},
		animateOut: function(settings, self) {
			methods.setupOut(settings, self);
			methods.startOut(self);
			return self;
		},
		setupIn: function(settings, self) {
			var data = {
				settings: settings,
				left: parseInt(self.css('left')),
				top: parseInt(self.css('top')),
				marginLeft: parseInt(self.css('margin-left')),
				marginRight: parseInt(self.css('margin-top'))
			};
			var container = methods._getContainer(settings, self);
			container.css('overflow', 'hidden');
			self.data($.maskFade.DATA, data);
			switch (settings.direction) {
				case $.maskFade.TOP_TO_BOTTOM:
					container.height(0);
					break;
				case $.maskFade.LEFT_TO_RIGHT:
					container.width(0);
					break;
				case $.maskFade.RIGHT_TO_LEFT:
					container.width(0);
					break;
			}
			return self;
		},
		startIn: function(self) {
//			alert('Mask fade start in');
			var container = self.parent();
			var data = self.data($.maskFade.DATA);
			var settings = data.settings;
			if (data != null) {
				setTimeout(function() {
					switch (settings.direction) {
						case $.maskFade.TOP_TO_BOTTOM:
//							alert(self.html() + ': ' + self.width());
							self.height(self.height());
							container.height(settings.verticalOffset).animate({
								height: self.height()
							}, settings.duration, settings.easeType, function() {
								self.data($.maskFade.DATA, null);
								if (settings.completeHandler != null) {
									settings.completeHandler();
								}
							});
							break;
						case $.maskFade.LEFT_TO_RIGHT:
//							alert(self.html() + ': ' + self.width());
							self.width(self.width());
							container.height(self.height()).width(settings.horizontalOffset).animate({
								width: self.width()
							}, settings.duration, settings.easeType, function() {
								self.data($.maskFade.DATA, null);
								if (settings.completeHandler != null) {
									settings.completeHandler();
								}
							});
							break;
						case $.maskFade.RIGHT_TO_LEFT:
							var width = self.width();
							self.width(self.width());
							if (container.css('position') == 'absolute') {
								container.css('left', width - settings.horizontalOffset).width(settings.horizontalOffset).animate({
									width: width,
									left: data.left
								}, settings.duration, settings.easeType, function() {
									self.data($.maskFade.DATA, null);
									if (settings.completeHandler != null) {
										settings.completeHandler();
									}
								});
							}
							else {
								container.css('margin-left', width - settings.horizontalOffset).width(settings.horizontalOffset).animate({
									width: width,
									marginLeft: data.marginLeft
								}, settings.duration, settings.easeType, function() {
									self.data($.maskFade.DATA, null);
									if (settings.completeHandler != null) {
										settings.completeHandler();
									}
								});
							}
							break;
					}
				}, settings.delay);
			}
			return self;
		},
		animateIn: function(settings, self) {
			methods.setupIn(settings, self);
			methods.startIn(self);
			return self;
		}
	};
	
	$.fn.maskFade = function(settings) {
		settings = $.extend( {
			action: $.maskFade.ANIMATE_IN,
			direction: $.maskFade.LEFT_TO_RIGHT,
			width: null,
			height: null,
			easeType: 'easeOutQuad',
			duration: 400,
			horizontalOffset: 0,
			verticalOffset: 0,
			delay: 0,
			completeHandler: null,
			left: null,
			top: null
		}, settings);
		
		switch (settings.action) {
			case $.maskFade.SETUP:
				return methods.setup(settings, this);
			case $.maskFade.SETUP_IN:
				return methods.setupIn(settings, this);
			case $.maskFade.START_IN:
				return methods.startIn(this);
			case $.maskFade.ANIMATE_IN:
				return methods.animateIn(settings, this);
			case $.maskFade.SETUP_OUT:
				return methods.setupOut(settings, this);
			case $.maskFade.START_OUT:
				return methods.startOut(this);
			case $.maskFade.ANIMATE_OUT:
				return methods.animateOut(settings, this);
		}
	};

	$.maskFade = {
		DATA: 'MASK-FADE',
		CONTAINER_CLASS: 'famteam-mask-fade',
		
		SETUP: 'setup',
		SETUP_IN: 'setup-in',
		START_IN: 'start-in',
		ANIMATE_IN: 'animate-in',
		SETUP_OUT: 'setup-out',
		START_OUT: 'start-out',
		ANIMATE_OUT: 'animate-out',
		
		TOP_TO_BOTTOM: 1,
		LEFT_TO_RIGHT: 0,
		RIGHT_TO_LEFT: 2
	};
})(jQuery);